// Use of this source code is governed by a BSD-style license
// that can be found in the License file.

#ifndef MUDUO_BASE_COUNTDOWNEVENT_H
#define MUDUO_BASE_COUNTDOWNEVENT_H

#include <cassert>
#include <chrono>
#include <condition_variable>
#include <mutex>

#include "CopyPolicy.h"

namespace muduo {

class CountDownEvent : public NonCopyable {
public:
    explicit CountDownEvent(int initial_count = 0) : count_(initial_count) {
        assert(initial_count >= 0);
    }

    // 阻塞等待计数减为0
    void wait() {
        std::unique_lock<std::mutex> lock(mutex_);
        condition_.wait(lock, [this] { return count_ == 0; });
    }

    // 带超时的等待（返回值：true=计数到0，false=超时）
    bool wait(unsigned int timeout_ms) {
        std::unique_lock<std::mutex> lock(mutex_);
        return condition_.wait_for(lock, std::chrono::milliseconds(timeout_ms),
                                   [this] { return count_ == 0; });
    }

    // 计数减1
    void countDown() { subCount(1); }

    // 计数增加n（n为非负数）
    void addCount(int n) {
        assert(n >= 0);
        std::lock_guard<std::mutex> lock(mutex_);
        count_ += n;
    }

    // 计数减少n（n为非负数，若n超过当前计数则置为0）
    void subCount(int n) {
        assert(n >= 0);
        std::lock_guard<std::mutex> lock(mutex_);
        const int old_count = count_;
        count_ = (n >= old_count) ? 0 : (old_count - n);
        if (old_count > 0 && count_ == 0) {
            condition_.notify_all();
        }
    }

    // 获取当前计数
    int getCount() const {
        std::lock_guard<std::mutex> lock(mutex_);
        return count_;
    }

    // 重置计数（仅在计数为0时有效）
    void reset(int new_count) {
        assert(new_count >= 0);
        std::lock_guard<std::mutex> lock(mutex_);
        assert(count_ == 0);  // 避免在等待状态下重置
        count_ = new_count;
    }

private:
    mutable std::mutex mutex_;
    std::condition_variable condition_;
    int count_;  // 受mutex_保护
};

}  // namespace muduo
#endif  // MUDUO_BASE_COUNTDOWNEVENT_H
